package cn.sdormitory.component.bindValue.bean.info;

import cn.hutool.core.convert.Convert;
import cn.sdormitory.common.utils.ContainerUtil;
import cn.sdormitory.component.bindValue.bean.VariableEntry;
import com.google.common.collect.HashBasedTable;
import com.google.common.collect.Table;
import lombok.Data;
import lombok.experimental.Accessors;
import org.jetbrains.annotations.Nullable;
import org.springframework.util.ReflectionUtils;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.*;
import java.util.stream.Collectors;

@Data
@Accessors(chain = true)
public class AnnotationInfo<T> {
    private T target;
    private String targetSuffixName;
    private String key;
    private Field targetField;
    private Field variableField;
    private List<Field> paramFields;
    private List<String> paramAliasList;
    private String defaultValue;
    private Class<? extends Annotation> annotationClass;

    private static final Table<String,String,String> EMPTY_TABLE = new EmptyTable();

    public boolean hasParamFields(){
        return ContainerUtil.notEmpty(paramFields);
    }

    public AnnotationInfo<T> setDefaultValue(String defaultValue) {
        if(defaultValue == null){
            return this;
        }
        if(defaultValue.equals("null->Null<-null")){
            this.defaultValue = null;
        }
        return this;
    }

    public List<VariableEntry> generateVariableEntry(List<?> list) {
        List<VariableEntry> entries = new ArrayList<>(list.size());
        for (int i = 0; i < list.size(); i++) {
            Object item = list.get(i);
            if(item == null){
                continue;
            }
            String value = getVariableFieldValueToStr(item);
            if(value != null){
                entries.add(new VariableEntry(i,value));
            }
        }
        return entries;
    }

    public List<String> generateVariables(List<?> list) {
        // 从待处理数据列表获取变量值列表 如字典value 行业id等
        return list.stream()
                .map(this::getVariableFieldValueToStr)
                .filter(Objects::nonNull)
                .distinct()
                .collect(Collectors.toList());
    }

    public Table<String,String,String> getEmptyParams(){
        return EMPTY_TABLE;
    }

    public Table<String,String,String> generateParams(List<?> list,List<VariableEntry> entries) {
        if(ContainerUtil.isEmpty(entries)){
            return EMPTY_TABLE;
        }
        Table<String,String,String> table = HashBasedTable.create();
        for (VariableEntry entry : entries) {
            Object item = list.get(entry.getIndex());
            for (int i = 0; i < paramFields.size(); i++) {
                Field paramField = paramFields.get(i);
                String paramValueStr = getFieldValueToStr(item, paramField);
                if(paramValueStr != null){
                    String paramAlias = paramAliasList.get(i);
                    table.put(entry.getVariable(),paramAlias,paramValueStr);
                }
            }
        }
        return table;
    }

    private String getVariableFieldValueToStr(Object item) {
        return getFieldValueToStr(item, variableField);
    }

    private String getFieldValueToStr(Object item,Field field) {
        return Convert.toStr(ReflectionUtils.getField(field, item));
    }

    private static class EmptyTable implements Table<String,String,String> {

        @Override
        public boolean contains(@Nullable Object o, @Nullable Object o1) {
            return false;
        }

        @Override
        public boolean containsRow(@Nullable Object o) {
            return false;
        }

        @Override
        public boolean containsColumn(@Nullable Object o) {
            return false;
        }

        @Override
        public boolean containsValue(@Nullable Object o) {
            return false;
        }

        @Override
        public @Nullable String get(@Nullable Object o, @Nullable Object o1) {
            return null;
        }

        @Override
        public boolean isEmpty() {
            return true;
        }

        @Override
        public int size() {
            return 0;
        }

        @Override
        public void clear() {

        }

        @Override
        public @Nullable String put(String s, String s2, String s3) {
            return null;
        }

        @Override
        public void putAll(Table<? extends String, ? extends String, ? extends String> table) {

        }

        @Override
        public @Nullable String remove(@Nullable Object o, @Nullable Object o1) {
            return null;
        }

        @Override
        public Map<String, String> row(String s) {
            return Collections.emptyMap();
        }

        @Override
        public Map<String, String> column(String s) {
            return Collections.emptyMap();
        }

        @Override
        public Set<Cell<String, String, String>> cellSet() {
            return Collections.emptySet();
        }

        @Override
        public Set<String> rowKeySet() {
            return Collections.emptySet();
        }

        @Override
        public Set<String> columnKeySet() {
            return Collections.emptySet();
        }

        @Override
        public Collection<String> values() {
            return Collections.emptyList();
        }

        @Override
        public Map<String, Map<String, String>> rowMap() {
            return Collections.emptyMap();
        }

        @Override
        public Map<String, Map<String, String>> columnMap() {
            return Collections.emptyMap();
        }
    }
}
